package cn.fr4nk.crawler.handler;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;

import cn.fr4nk.crawler.proxy.BaseProxyPool;
import cn.fr4nk.crawler.proxy.Proxy;
import cn.fr4nk.crawler.proxy.ProxyPool;
import cn.fr4nk.crawler.task.AbstractHandler;
import cn.fr4nk.crawler.task.CrawlerTask;
import cn.fr4nk.crawler.utils.ProxyUtil;
import cn.fr4nk.crawler.utils.WebDriverUtil;

@SuppressWarnings("rawtypes")
public abstract class AbstractCrawlerHandler extends AbstractHandler<CrawlerTask> {

	private static Log log = LogFactory.getLog(AbstractCrawlerHandler.class);
	
	protected int handlerIndex = 0;
	private ProxyPool proxyPool = BaseProxyPool.getInstance();
	protected String proxyPrefix = ""; // qyxx
	protected boolean useProxy = false;
	protected int waitTime = 30;
	protected String webDriverType = "HTML_UNIT"; // chrome headless or HTMLUNIT
	

	/**
	 * 根据task里设置的handler来匹配
	 * 
	 * @param CrawlerTask
	 * @return boolean
	 */
	public boolean checkTask(CrawlerTask task) {
		if (null == task || StringUtils.isEmpty(task.getUrl()) || StringUtils.isEmpty(task.getHandler())) {
			return false;
		}
		return task.getHandler().equals(this.getClass().toString().substring(6));
	}
	protected Proxy getAvaliableProxy(String prefix) {
		Proxy proxy = null;
		if (useProxy) {
			proxy = BaseProxyPool.getInstance().get(prefix);
			while (!ProxyUtil.checkProxyJsoup(proxy)) {
				if (proxy != null) {
					log.debug(proxy.getIpPort() + " not working, so deleting it");
					BaseProxyPool.getInstance().remove(prefix, proxy);
				}
				proxy = BaseProxyPool.getInstance().get(prefix);
			}
			log.debug("使用代理[" + proxy.getIpPort() + "]");
		}
		return proxy;
	}
	public int getHandlerIndex() {
		return handlerIndex;
	}
	protected String getPageSourceJson(WebDriver driver) throws Exception {
		String pageSource = "";
		if (driver instanceof HtmlUnitDriver) {
			pageSource = driver.getPageSource();
		} else if (driver instanceof ChromeDriver) {
			pageSource =  driver.findElement(By.tagName("body")).getText().toString();
		} else {
			throw new Exception("未知的selenium driver类型，解析页面上json失败");
		}
		return pageSource;
	}
	public ProxyPool getProxyPool() {
		return proxyPool;
	}
	public String getProxyPrefix() {
		return proxyPrefix;
	}

	public int getWaitTime() {
		return waitTime;
	}
	
	
	protected WebDriver getWebdriver() {
		return getWebdriver(proxyPrefix);
	}

	protected WebDriver getWebdriver(String prefix) {
		Proxy proxy  = getAvaliableProxy(prefix);
		if (webDriverType.equals("HTML_UNIT")) {
			return WebDriverUtil.createHtmlUnit(proxy);
		} else if (webDriverType.equals("CHROME_HEADLESS")) {
			return WebDriverUtil.createChrome(true, proxy);
		} else if (webDriverType.equals("CHROME")) {
			return WebDriverUtil.createChrome(false, proxy);
		} else {
			return WebDriverUtil.createHtmlUnit(proxy);
		}
	}

	protected WebDriver getWebdriver(String prefix, boolean enableJs) {
		Proxy proxy  = getAvaliableProxy(prefix);
		if (webDriverType.equals("HTML_UNIT")) {
			return WebDriverUtil.createHtmlUnit(proxy, enableJs);
		} else if (webDriverType.equals("CHROME_HEADLESS")) {
			return WebDriverUtil.createChrome(true, proxy, enableJs);
		} else if (webDriverType.equals("CHROME")) {
			return WebDriverUtil.createChrome(false, proxy, enableJs);
		} else {
			return WebDriverUtil.createHtmlUnit(proxy);
		}
	}
	

	public String getWebDriverType() {
		return webDriverType;
	}

	/**
	 * 责任链模式: 如果自己无法处理（或者不该处理），则让下一个责任人处理
	 */
	@Override
	public abstract void handle(CrawlerTask task) throws Exception ;
	
	public boolean isUseProxy() {
		return useProxy;
	}


	public void setHandlerIndex(int handlerIndex) {
		this.handlerIndex = handlerIndex;
	}

	public void setProxyPool(ProxyPool proxyPool) {
		this.proxyPool = proxyPool;
	}

	public void setProxyPrefix(String proxyPrefix) {
		this.proxyPrefix = proxyPrefix;
	}


	public void setUseProxy(boolean useProxy) {
		this.useProxy = useProxy;
	}

	public void setWaitTime(int waitTime) {
		this.waitTime = waitTime;
	}

	public void setWebDriverType(String webDriverType) {
		this.webDriverType = webDriverType;
	}

}
